土day來挑戰的題目:
這題給了四個檔案:
level5.py(檢查器)
level5.flag.txt.enc(被 XOR 加密的 flag)
level5.hash.bin(正確密碼的 hash bytes)
dictionary.txt(可能的密碼字典)
預估流程(馬後炮):從題目或字典取得可能的密碼候選 → 用與檢查器同樣的 hash 方法將候選雜湊 → 與 level5.hash.bin 比對找出正確密碼 → 用該密碼當 key 做 XOR 還原 flag。
解題步驟與思路
一、先下載題目檔:
wget https://artifacts.picoctf.net/c/31/level5.py
wget https://artifacts.picoctf.net/c/31/level5.flag.txt.enc
wget https://artifacts.picoctf.net/c/31/level5.hash.bin
wget https://artifacts.picoctf.net/c/31/dictionary.txt
ls -1
二、先檢視 level5.py 看檢查邏輯(是否有直接的 pos_pw_list、使用哪種 hash):
cat level5.py
flag_enc = open('level5.flag.txt.enc', 'rb').read()
correct_pw_hash = open('level5.hash.bin', 'rb').read()
def hash_pw(pw_str):
pw_bytes = bytearray()
pw_bytes.extend(pw_str.encode())
m = hashlib.md5()
m.update(pw_bytes)
return m.digest()
def level_5_pw_check():
user_pw = input("Please enter correct password for flag: ")
user_pw_hash = hash_pw(user_pw)
if( user_pw_hash == correct_pw_hash ):
print("Welcome back... your flag, user:")
decryption = str_xor(flag_enc.decode(), user_pw)
print(decryption)
return
print("That password is incorrect")
解讀重點:
三、我使用的 Python 自動化判定腳本(把 dictionary 當候選,嘗試常見 hash 與少量變形):
python3 - <<'PY'
import hashlib,os,re
cands=[]
if os.path.exists('level5.py'):
src=open('level5.py','r',encoding='utf-8',errors='ignore').read()
m=re.search(r'pos_pw_list\s*=\s*\[([^\]]*)\]',src,re.S)
if m:
cands=re.findall(r"""['"]([^'"]+)['"]""", m.group(1))
if not cands:
with open('dictionary.txt','r',encoding='utf-8',errors='ignore') as f:
cands=[l.strip() for l in f if l.strip()]
target=open('level5.hash.bin','rb').read()
algs=['md5','sha1','sha256','sha512']
transforms=[lambda s:s, lambda s:s.lower(), lambda s:s.upper(), lambda s:s.strip()]
suffixes=['','1','123','!']
for i,p in enumerate(cands):
if i%1000==0:
print("試到候選 #",i)
for tf in transforms:
base=tf(p)
for suf in suffixes:
pw=base+suf
for alg in algs:
d=getattr(hashlib,alg)(pw.encode()).digest()
if d==target:
print("FOUND:", pw, "alg:", alg)
raise SystemExit
print("No match found")
PY
四、找到密碼後,用 str_xor 邏輯解密 level5.flag.txt.enc(以下把 THE_PASSWORD 換成找到的密碼):
python3 - <<'PY'
def str_xor(secret, key):
new_key = key
i = 0
while len(new_key) < len(secret):
new_key = new_key + key[i]
i = (i + 1) % len(key)
return "".join([chr(ord(a) ^ ord(b)) for a,b in zip(secret,new_key)])
enc = open('level5.flag.txt.enc','rb').read()
try:
s = enc.decode()
except:
s = enc.decode('latin-1')
print(str_xor(s, "THE_PASSWORD"))
PY
一頓操作後就得到正確Flag啦!
picoCTF{h45h_sl1ng1ng_36e992a6}
排錯小技巧
檢查 level5.py 是否對輸入做了前處理(strip/lower/replace、加 salt 等)。
看 level5.hash.bin 長度判斷 hash 類型:
16 bytes → MD5
20 bytes → SHA1
32 bytes → SHA256
64 bytes → SHA512
命令: wc -c level5.hash.bin(顯示 bytes)
若 enc.decode() 失敗,先用 latin-1 或直接以 bytes 做 XOR 再篩選 ASCII printable。
學習心得
這題是把字典、雜湊與 XOR 三個常見概念串在一起的好題型。
實務上最重要的習慣是「讀懂檔案和程式」,把題目提供的線索當作首選候選,然後用小腳本自動化驗證。
解題完成之後記得把步驟和常用腳本紀錄下來,下一次遇到類似題型會更快。